package com.marvels.system.common.service.impl;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;

import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import com.marvels.common.constants.MarvelsConstant;
import com.marvels.common.dao.UserRechargeLogDao;
import com.marvels.common.dto.MarvelsResultDTO;
import com.marvels.common.dto.UserDTO;
import com.marvels.common.dto.UserLoginInfoDTO;
import com.marvels.common.dto.UserRechargeLogDTO;
import com.marvels.common.exception.MarvelsBusinessException;
import com.marvels.common.exception.MarvelsErrorCode;
import com.marvels.common.utils.AsyncExecuteApi;
import com.marvels.common.utils.CacheUtils;
import com.marvels.common.utils.MarvelsLogUtil;
import com.marvels.common.utils.MarvelsUtils;
import com.marvels.common.utils.ShaUtils;
import com.marvels.system.common.service.SysLoginService;
import com.marvels.system.common.service.SysMenuService;
import com.marvels.system.permission.dao.McsmUserLoginLogMapper;
import com.marvels.system.permission.dao.SysUserDao;
import com.marvels.system.permission.dto.McsmUserLoginLog;
import com.marvels.system.permission.dto.SysUserDTO;
import com.marvels.system.permission.dto.SysUserRoleDTO;

import cn.hutool.core.util.StrUtil;

@Service
public class SysLoginServiceImpl implements SysLoginService {
	@Autowired
	private SysUserDao sysUserDao;
	@Autowired
	private McsmUserLoginLogMapper mcsmUserLoginLogMapper;
	@Autowired
	SysMenuService sysMenuService;
	@Autowired
	private UserRechargeLogDao userRechargeLogDao;
	@Autowired
	private AsyncExecuteApi asyncExecuteApi;
	@Value("${platform.name.code}")
    private String platformNameCode;
	
	@Override
	public MarvelsResultDTO login(UserDTO params,HttpServletRequest request) throws MarvelsBusinessException {
		//判断用户是否已经登录
		if(CacheUtils.isLogin()){
			return MarvelsResultDTO.getResult(MarvelsErrorCode.SUCCESS.getValue(), MarvelsErrorCode.SUCCESS.getDesc(), null);
		}
		if(params == null){
			return MarvelsResultDTO.getResult(MarvelsErrorCode.USER_NAME_NULL.getValue(), MarvelsErrorCode.USER_NAME_NULL.getDesc(), null);
		}
		//用户名不能为空
		if(StringUtils.isEmpty(params.getUserCode())){
			return MarvelsResultDTO.getResult(MarvelsErrorCode.USER_NAME_NULL.getValue(), MarvelsErrorCode.USER_NAME_NULL.getDesc(), null);
		}
		//密码不能为空
		if(StringUtils.isEmpty(params.getUserPwd())){
			return MarvelsResultDTO.getResult(MarvelsErrorCode.USER_PWD_NULL.getValue(), MarvelsErrorCode.USER_PWD_NULL.getDesc(), null);
		}
		//用户名校验
		List<SysUserDTO> list = sysUserDao.selectUserByUserCode(params.getUserCode());
		if(CollectionUtils.isEmpty(list)){
			//用户名不存在
			return MarvelsResultDTO.getResult(MarvelsErrorCode.USER_NOT_EXIST.getValue(), MarvelsErrorCode.USER_NOT_EXIST.getDesc(), null);
		}else if(list.size() > 1){
			//相同用户名存在多个用户
			return MarvelsResultDTO.getResult(MarvelsErrorCode.USER_COUNT_EXP.getValue(), MarvelsErrorCode.USER_COUNT_EXP.getDesc(), null);
		}else{
			SysUserDTO user = list.get(0);
			//入参密码加密
			//String pwd =ShaUtils.Encrypt(params.getUserPwd(), "MD5");
			if(!StringUtils.equals(params.getUserPwd(), user.getUserPwd())){
				// 异步执行登录封禁IP
				asyncExecuteApi.loginTransfinite();
				//密码错误
				String loginIp = MarvelsUtils.getIpAddr(request);
				insertLoginLog(user, loginIp, 1, "密码错误");
				return MarvelsResultDTO.getResult(MarvelsErrorCode.USER_PWD_ERROR.getValue(), MarvelsErrorCode.USER_PWD_ERROR.getDesc(), null);
			}
			
			if(!StrUtil.equals(user.getUserCode(), MarvelsConstant.SYSTEM_SUPER_CODE)){
				UserRechargeLogDTO userRechargeLogDTO = userRechargeLogDao.selectUserRechargeLog();
				if(userRechargeLogDTO != null && userRechargeLogDTO.getUsageState() == 1){
					return MarvelsResultDTO.getResult("0002", "该系统已欠费，目前无法登陆，详情请咨询相关负责人。", null);
				}
			}
			
			UserDTO u = convert2User(user);
			String loginIp = MarvelsUtils.getIpAddr(request);
			if(StringUtils.isBlank(u.getLastLoginIp()))
				u.setLastLoginIp(loginIp);
			if(u.getLastLoginTime() == null)
				u.setLastLoginTime(new Date());
				
			// 原新核心记录登陆日志信息
			sysUserDao.insertLoginInfo(user.getUserCode(), loginIp);
			// 记录登陆日志信息并且更新用户表（新）
			insertLoginLog(user, loginIp, 0, "登陆成功");
			updateLoginLog(user, loginIp);
			try {
				Map<String, String> map = sysMenuService.getPermissionMap(user.getUserCode());
				Map<String, String> urlmMap = sysMenuService.getPermissionUrlMap(user.getUserCode());
				CacheUtils.cacheObject("permission"+user.getUserCode(), map);
				CacheUtils.cacheObject("urlPermission"+user.getUserCode(), urlmMap);
				u.setAuthCodeMap(map);
				//登录缓存
				CacheUtils.cacheUser(u, platformNameCode);
			}catch(Exception e) {
				MarvelsLogUtil.getInstance().error("缓存权限码失败，UserCode="+user.getUserCode(), e);
			}
			return MarvelsResultDTO.getResult(MarvelsErrorCode.SUCCESS.getValue(), MarvelsErrorCode.SUCCESS.getDesc(), u);
		}
	}
	
	private void updateLoginLog(SysUserDTO user, String loginIp) {
		// 更新用户表
		Date date = new Date();
		user.setLastLoginIp(loginIp);
		user.setLastLoginTime(date);
		user.setUpdatedDate(date);
		user.setUpdatedBy(user.getUserCode());
		sysUserDao.updateByPrimaryKeySelective(user);
	}
	
	// 保存登陆日志信息
	private void insertLoginLog(SysUserDTO user, String loginIp, int status, String msg) {
		// 保存登陆日志信息
		McsmUserLoginLog record = new McsmUserLoginLog();
		record.setUserId(new Long(user.getUserId()));
		record.setUserCode(user.getOrgCode());
		record.setUserName(user.getUserNamep());
		record.setRealName(user.getRealName());
		record.setStatus(status);
		record.setMsg(msg);
		record.setLoginIp(loginIp);
		record.setLoginTime(new Date());
		record.setCreatedBy(user.getUserCode());
		record.setUpdatedBy(user.getUserCode());
		mcsmUserLoginLogMapper.insertSelective(record);
	}

	/**
	 * 系统用户DTO转换成登录用户DTO
	 * @param param
	 * @return
	 */
	private UserDTO convert2User(SysUserDTO param){
		UserDTO user = new UserDTO();
		user.setUserId(param.getUserId());
		user.setOrgCode(param.getOrgCode());
		user.setUserCode(param.getUserCode());
		user.setUserName(param.getUserNamep());
		user.setUserPwd(param.getUserPwd());
		user.setRealName(param.getRealName());
		user.setPositionCode(param.getPositionCode());
		user.setPositionName(param.getPositionName());
		List<SysUserRoleDTO> roles = param.getRoles();
		if(CollectionUtils.isNotEmpty(roles)){
			List<String> roleCodes = new ArrayList<String>();
			for(SysUserRoleDTO role : roles){
				roleCodes.add(role.getRoleCode());
			}
			user.setRoleCodes(roleCodes);
		}
		UserLoginInfoDTO loginInfo = sysUserDao.selectLastLoginInfo(param.getUserCode());
		if(loginInfo != null){
			user.setLastLoginIp(loginInfo.getLoginIp());
			user.setLastLoginTime(loginInfo.getLoginTime());
		}
		return user;
	}

	@Override
	public void logout() throws MarvelsBusinessException {
		UserDTO  dto = CacheUtils.getCacheUser();
		CacheUtils.delCacheUser();
		CacheUtils.delete("permission"+dto.getUserCode());
		CacheUtils.delete("urlPermission"+dto.getUserCode());
	}
	
	@Override
	public void editPassword(Map<String, String> request) throws MarvelsBusinessException {
		String oldPwd = request.get("oldPwd");
		String newPwd = request.get("newPwd");
		String confirmPwd = request.get("confirmPwd");
		if(StringUtils.isEmpty(oldPwd) || StringUtils.isEmpty(newPwd) || StringUtils.isEmpty(confirmPwd)){
			throw new MarvelsBusinessException("旧密码，新密码，确认密码均不能为空");
		}
		UserDTO user = CacheUtils.getCacheUser();
		String oldPwdMD5 = ShaUtils.Encrypt(oldPwd, "MD5");
		if(!StringUtils.equals(oldPwdMD5, user.getUserPwd())){
			throw new MarvelsBusinessException("旧密码不正确");
		}
		if(!StringUtils.equals(newPwd, confirmPwd)){
			throw new MarvelsBusinessException("新密码和确认密码不一致");
		}
		String newPwdMD5 = ShaUtils.Encrypt(newPwd, "MD5");
		SysUserDTO u = new SysUserDTO();
		u.setUserId(user.getUserId());
		u.setUserPwd(newPwdMD5);
		u.setUpdatedBy(user.getUserCode());
		sysUserDao.updatePassword(u);
	}
	
	@Override
	public void initPassword(SysUserDTO user) throws MarvelsBusinessException {
		if(user == null || user.getUserId() == null || user.getUserId() < 1){
			throw new MarvelsBusinessException("入参不能为空");
		}
		user.setUpdatedBy(user.obtainLoginUserName());
		user.setUserPwd(ShaUtils.Encrypt(user.getUserPwd(), "MD5"));
		sysUserDao.updatePassword(user);
	}
	
}
